﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management.Automation;

namespace pshcli
{
    [Cmdlet("Run","Dwarf")]
    public class PSH_RunDwarf:Cmdlet
    {
        private Dwarf dwarf;
        private List<Dwarf> dwarflist;

        [Parameter(
            Position = 0,
            ValueFromPipeline = true,
            Mandatory = false,
            HelpMessage = "Dwarf object to be executed")]
        public Dwarf Dwarf
        {
            get { return dwarf; }
            set { dwarf = value; }
        }

        ProgressRecord all;
        int dall;
        int failedcount;

        protected override void BeginProcessing()
        {
            all = new ProgressRecord(1, "Total dwarf execution:", "Progress...");
            all.PercentComplete = 0;
            dwarflist = new List<Dwarf>();
            failedcount = 0;
        }

        protected override void  ProcessRecord()
        {
            if (dwarf == null)
                throw new Exception("RUN-DWARF-ERROR: Null-object passed as input.");
            
            dwarflist.Add((Dwarf)dwarf);
        }


        protected override void EndProcessing()
        {
            dall = (int)(100 / dwarflist.ToArray().Length);
            this.WriteProgress(all);

            foreach (Dwarf d in dwarflist.ToArray())
            {
                this.WriteVerbose(
                    "RUN-DWARF: Executing: " +
                    d.dwarfname + ", " +
                    d.platform + ", " +
                    d.parallel + ", " +
                    d.size + ". \n");

                d.success = false;

                if (d.parallel != parallel.serial)
                {
                    this.WriteVerbose(
                        "RUN-DWARF: Number of processes/threads:" +
                        d.numthreads);
                }

                this.WriteVerbose(
                    "RUN-DWARF: Execution string: " +
                    d.ConstructExecCommand());

                all.StatusDescription = "Progress (" + d.dwarfname + "," + d.platform + "," + d.parallel + "," + d.size + ")...";

                Console.Write(d.dwarfname + "." + d.platform + "." + d.parallel + "." + d.size + " started...");

                //Old call
                //string consistent = d.CeckConsistency();
                string consistent = null; //let's make this work without any tests

                if (String.IsNullOrEmpty(consistent))
                {
                    if (d.xperftrace && String.IsNullOrEmpty(d.scheduler))
                    {
                        this.WriteVerbose("RUN-DWARF: Starting tracing.");
                        this.WriteVerbose("RUN-DWARF: Trace file: " + d.xperftracefile);
                        HelperMethods.StartXperf(d.xperftracefile);
                    }
                    else //this should be in get-dwarf
                        d.xperftrace = false;

                    double totalProcTime = 0;

                    System.Diagnostics.Stopwatch stopw = new System.Diagnostics.Stopwatch();
                    stopw.Start();

                    if (!HelperMethods.ExecuteDwarf(d, ref totalProcTime))
                        Console.WriteLine("Execution failed with the following message: " + d.errormsg);

                    stopw.Stop();
                    totalProcTime = stopw.ElapsedMilliseconds / (double)1000;
                    stopw.Reset();

                    if (d.xperftrace && String.IsNullOrEmpty(d.scheduler))
                        HelperMethods.StopXperf();


                    if (d.success)
                    {
                        d.GetResult();
                        Console.WriteLine(" done. Kernel time: " + d.time + " seconds");
                        Console.WriteLine("Total processor time: " + totalProcTime + " seconds");
                    }
                }
                else
                {
                    Console.WriteLine("Configuration error, skipping execution.");
                    this.WriteVerbose("Error message: " + consistent);

                    d.success = false;
                    d.errormsg += consistent;
                    failedcount++;
                }

                this.WriteObject(d);       
                all.PercentComplete += dall;
                this.WriteProgress(all);
            }

            all.PercentComplete = 100;
            this.WriteProgress(all);
            if (failedcount > 0)
                Console.WriteLine("\nFailed: " + failedcount);
            
        }


    }
}
